/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern crate alloc;

use alloc::boxed::Box;
use crate::BTreeMap;

use crate::common::constants::*;
use crate::log_e;
use crate::traits::auth_policy_manager::{AuthPolicy, AuthPolicyManager};

const MAX_NUMBER_OF_FACE_PER_USER: usize = 1;
const MAX_NUMBER_OF_FINGERS_PER_USER: usize = 5;
const MAX_NUMBER_OF_PIN_PER_USER: usize = 1;

struct PinAuthPolicy;
impl AuthPolicy for PinAuthPolicy {
    fn auth_type(&self) -> AuthType {
        AuthType::Pin
    }

    fn require_pin_before_enrollment(&self) -> bool {
        false
    }

    fn depends_on_pin(&self) -> bool {
        false
    }

    fn get_max_credential_number_per_user(&self) -> usize {
        MAX_NUMBER_OF_PIN_PER_USER
    }
}

struct FaceAuthPolicy;
impl AuthPolicy for FaceAuthPolicy {
    fn auth_type(&self) -> AuthType {
        AuthType::Face
    }

    fn require_pin_before_enrollment(&self) -> bool {
        true
    }

    fn depends_on_pin(&self) -> bool {
        false
    }

    fn get_max_credential_number_per_user(&self) -> usize {
        MAX_NUMBER_OF_FACE_PER_USER
    }
}

struct FingerprintAuthPolicy;
impl AuthPolicy for FingerprintAuthPolicy {
    fn auth_type(&self) -> AuthType {
        AuthType::Fingerprint
    }

    fn require_pin_before_enrollment(&self) -> bool {
        true
    }

    fn depends_on_pin(&self) -> bool {
        false
    }

    fn get_max_credential_number_per_user(&self) -> usize {
        MAX_NUMBER_OF_FINGERS_PER_USER
    }
}

pub struct DefaultAuthPolicyManager {
}

impl DefaultAuthPolicyManager {
    pub fn new() -> Self {
        Self{}
    }
}

impl AuthPolicyManager for DefaultAuthPolicyManager {
    fn get_auth_policy(&self, auth_type: AuthType) -> Result<Box<dyn AuthPolicy>, ErrorCode> {
        match auth_type {
            AuthType::Pin => Ok(Box::new(PinAuthPolicy)),
            AuthType::Face => Ok(Box::new(FaceAuthPolicy)),
            AuthType::Fingerprint => Ok(Box::new(FingerprintAuthPolicy)),
            _ => {
                log_e!("Auth policy not found for auth type: {:?}", auth_type);
                Err(ErrorCode::GeneralError)
            }
        }
    }
}
